// PWA推送通知服务 - 支持后台通知和离线功能
export interface PWANotificationOptions {
  title: string;
  body?: string;
  icon?: string;
  badge?: string;
  tag?: string;
  data?: any;
  actions?: Array<{
    action: string;
    title: string;
    icon?: string;
  }>;
  requireInteraction?: boolean;
  silent?: boolean;
  vibrate?: number[];
  timestamp?: number;
  image?: string;
  dir?: 'auto' | 'ltr' | 'rtl';
  lang?: string;
  renotify?: boolean;
}

export interface PWASubscription {
  endpoint: string;
  keys: {
    p256dh: string;
    auth: string;
  };
}

export class PWANotificationService {
  private static instance: PWANotificationService;
  private serviceWorkerRegistration: ServiceWorkerRegistration | null = null;
  private pushSubscription: PushSubscription | null = null;
  private vapidPublicKey: string = ''; // 需要从服务器获取

  private constructor() {
    this.initializeServiceWorker();
  }

  public static getInstance(): PWANotificationService {
    if (!PWANotificationService.instance) {
      PWANotificationService.instance = new PWANotificationService();
    }
    return PWANotificationService.instance;
  }

  // 初始化Service Worker
  private async initializeServiceWorker(): Promise<void> {
    if (!('serviceWorker' in navigator)) {
      console.warn('此浏览器不支持Service Worker');
      return;
    }

    try {
      // 注册Service Worker
      this.serviceWorkerRegistration = await navigator.serviceWorker.register('/sw.js', {
        scope: '/'
      });

      console.log('Service Worker 注册成功:', this.serviceWorkerRegistration);

      // 等待Service Worker激活
      await this.waitForServiceWorkerReady();

      // 设置消息监听器
      this.setupMessageListener();

      // 检查现有的推送订阅
      await this.checkExistingSubscription();

    } catch (error) {
      console.error('Service Worker 注册失败:', error);
    }
  }

  // 等待Service Worker准备就绪
  private async waitForServiceWorkerReady(): Promise<void> {
    if (!this.serviceWorkerRegistration) return;

    return new Promise((resolve) => {
      if (this.serviceWorkerRegistration!.active) {
        resolve();
      } else {
        this.serviceWorkerRegistration!.addEventListener('updatefound', () => {
          const newWorker = this.serviceWorkerRegistration!.installing;
          if (newWorker) {
            newWorker.addEventListener('statechange', () => {
              if (newWorker.state === 'activated') {
                resolve();
              }
            });
          }
        });
      }
    });
  }

  // 设置消息监听器
  private setupMessageListener(): void {
    navigator.serviceWorker?.addEventListener('message', (event) => {
      const { type, data } = event.data || {};
      
      switch (type) {
        case 'NOTIFICATION_CLICKED':
          this.handleNotificationClick(data);
          break;
        case 'NOTIFICATION_CLOSED':
          this.handleNotificationClose(data);
          break;
        case 'NAVIGATION':
          this.handleNavigation(data.url);
          break;
        default:
          console.log('收到Service Worker消息:', event.data);
      }
    });
  }

  // 检查现有的推送订阅
  private async checkExistingSubscription(): Promise<void> {
    if (!this.serviceWorkerRegistration) return;

    try {
      this.pushSubscription = await this.serviceWorkerRegistration.pushManager.getSubscription();
      
      if (this.pushSubscription) {
        console.log('找到现有的推送订阅');
        // 可以在这里同步订阅状态到服务器
        await this.syncSubscriptionToServer(this.pushSubscription);
      }
    } catch (error) {
      console.error('检查推送订阅失败:', error);
    }
  }

  // 请求通知权限
  public async requestNotificationPermission(): Promise<NotificationPermission> {
    if (!('Notification' in window)) {
      console.warn('此浏览器不支持通知');
      return 'denied';
    }

    if (Notification.permission === 'granted') {
      return 'granted';
    }

    if (Notification.permission !== 'denied') {
      const permission = await Notification.requestPermission();
      return permission;
    }

    return Notification.permission;
  }

  // 订阅推送通知
  public async subscribeToPushNotifications(): Promise<PushSubscription | null> {
    console.log('🚀 开始PWA推送订阅流程...');
    
    // 检查是否在本地开发环境
    const isLocalhost = location.hostname === 'localhost' || location.hostname === '127.0.0.1';
    const isHTTP = location.protocol === 'http:';
    
    if (isLocalhost && isHTTP) {
      console.warn('⚠️ 检测到本地HTTP环境，PWA推送通知可能不被支持');
      console.log('💡 建议使用以下方案之一：');
      console.log('   1. 使用 https://localhost (需要SSL证书)');
      console.log('   2. 部署到HTTPS服务器测试');
      console.log('   3. 使用 ngrok 等工具创建HTTPS隧道');
    }
    
    if (!this.serviceWorkerRegistration) {
      console.error('❌ Service Worker 未注册');
      return null;
    }
    console.log('✅ Service Worker 已注册:', this.serviceWorkerRegistration);

    const permission = await this.requestNotificationPermission();
    console.log('🔔 通知权限状态:', permission);
    if (permission !== 'granted') {
      console.warn('❌ 通知权限被拒绝');
      return null;
    }

    try {
      // 获取VAPID公钥
      console.log('🔑 获取VAPID公钥...');
      await this.fetchVapidPublicKey();
      console.log('✅ VAPID公钥获取成功:', this.vapidPublicKey);

      // 检查推送管理器支持
      if (!this.serviceWorkerRegistration.pushManager) {
        throw new Error('浏览器不支持推送管理器');
      }

      // 检查现有订阅
      const existingSubscription = await this.serviceWorkerRegistration.pushManager.getSubscription();
      if (existingSubscription) {
        console.log('⚠️ 发现现有订阅，先取消:', existingSubscription);
        await existingSubscription.unsubscribe();
      }

      // 创建推送订阅
      console.log('📱 创建推送订阅...');
      console.log('🔧 订阅参数:', {
        userVisibleOnly: true,
        applicationServerKey: this.vapidPublicKey
      });

      try {
        // 添加超时机制
        const subscribePromise = this.serviceWorkerRegistration.pushManager.subscribe({
          userVisibleOnly: true,
          applicationServerKey: this.urlBase64ToUint8Array(this.vapidPublicKey) as BufferSource
        });

        // 根据环境设置不同的超时时间
        const isLocalhost = location.hostname === 'localhost' || location.hostname === '127.0.0.1';
        const isHTTP = location.protocol === 'http:';
        const timeoutMs = (isLocalhost && isHTTP) ? 10000 : 60000; // 本地环境10秒，生产环境60秒
        
        // 添加更多环境信息
        console.log('🌐 环境信息:', {
          hostname: location.hostname,
          protocol: location.protocol,
          userAgent: navigator.userAgent.substring(0, 100) + '...',
          vendor: navigator.vendor,
          language: navigator.language,
          onLine: navigator.onLine,
          serviceWorkerReady: !!this.serviceWorkerRegistration?.active,
          pushManagerAvailable: !!this.serviceWorkerRegistration?.pushManager
        });
        
        const timeoutPromise = new Promise((_, reject) => {
          setTimeout(() => {
            console.error('❌ 推送订阅超时分析:');
            console.error('   🕐 超时时间:', timeoutMs / 1000, '秒');
            console.error('   🌍 环境:', isLocalhost ? '本地' : '生产', isHTTP ? 'HTTP' : 'HTTPS');
            console.error('   🔧 可能原因:');
            console.error('      1. 网络连接不稳定');
            console.error('      2. 浏览器推送服务异常');
            console.error('      3. VAPID配置问题');
            console.error('      4. 防火墙或代理阻止');
            console.error('   💡 建议解决方案:');
            console.error('      1. 检查网络连接');
            console.error('      2. 尝试其他浏览器');
            console.error('      3. 检查浏览器推送设置');
            console.error('      4. 联系系统管理员');
            
            const envMsg = (isLocalhost && isHTTP) ? 
              '订阅超时：本地HTTP环境不支持PWA推送通知' : 
              `订阅超时：${timeoutMs/1000}秒内未完成`;
            reject(new Error(envMsg));
          }, timeoutMs);
        });

        console.log('⏳ 等待推送订阅响应...（超时时间:', timeoutMs / 1000, '秒）');
        this.pushSubscription = await Promise.race([subscribePromise, timeoutPromise]) as PushSubscription;
        console.log('✅ 推送订阅创建成功:', this.pushSubscription);
      } catch (subscribeError) {
        console.error('❌ 推送订阅创建失败:', subscribeError);
        
        // 尝试诊断具体问题
        await this.diagnosePushIssues();
        
        // 详细分析错误类型
        if (subscribeError instanceof DOMException) {
          console.error('🔍 DOMException详情:', {
            name: subscribeError.name,
            message: subscribeError.message,
            code: subscribeError.code
          });
        }
        
        throw subscribeError;
      }

      // 将订阅信息发送到服务器
      console.log('🔄 同步订阅信息到服务器...');
      await this.syncSubscriptionToServer(this.pushSubscription);
      console.log('✅ 订阅信息同步成功');

      return this.pushSubscription;
    } catch (error) {
      console.error('❌ 创建推送订阅失败:', error);
      return null;
    }
  }

  // 取消推送订阅
  public async unsubscribeFromPushNotifications(): Promise<boolean> {
    if (!this.pushSubscription) {
      console.warn('没有活跃的推送订阅');
      return true;
    }

    try {
      const success = await this.pushSubscription.unsubscribe();
      
      if (success) {
        // 从服务器删除订阅
        await this.removeSubscriptionFromServer(this.pushSubscription);
        this.pushSubscription = null;
        console.log('推送订阅已取消');
      }

      return success;
    } catch (error) {
      console.error('取消推送订阅失败:', error);
      return false;
    }
  }

  // 显示本地通知
  public async showNotification(options: PWANotificationOptions): Promise<void> {
    if (!this.serviceWorkerRegistration) {
      console.error('Service Worker 未注册');
      return;
    }

    const permission = await this.requestNotificationPermission();
    if (permission !== 'granted') {
      console.warn('通知权限被拒绝');
      return;
    }

    const notificationOptions = {
      body: options.body || '',
      icon: options.icon || '/icon-192x192.png',
      badge: options.badge || '/icon-192x192.png',
      tag: options.tag || `notification-${Date.now()}`,
      data: options.data || {},
      actions: options.actions || [],
      requireInteraction: options.requireInteraction || false,
      silent: options.silent || false,
      vibrate: options.vibrate || [200, 100, 200],
      timestamp: options.timestamp || Date.now(),
      image: options.image,
      dir: options.dir || 'auto',
      lang: options.lang || 'zh-CN',
      renotify: options.renotify || false
    };

    try {
      await this.serviceWorkerRegistration.showNotification(options.title, notificationOptions);
    } catch (error) {
      console.error('显示通知失败:', error);
    }
  }

  // 安排延迟通知
  public async scheduleNotification(
    options: PWANotificationOptions,
    delay: number
  ): Promise<void> {
    if (!this.serviceWorkerRegistration?.active) {
      console.error('Service Worker 未激活');
      return;
    }

    // 通过Service Worker安排延迟通知
    this.serviceWorkerRegistration.active.postMessage({
      type: 'SCHEDULE_NOTIFICATION',
      data: {
        notification: {
          title: options.title,
          options: {
            body: options.body,
            icon: options.icon || '/icon-192x192.png',
            badge: options.badge || '/icon-192x192.png',
            tag: options.tag,
            data: options.data,
            actions: options.actions,
            requireInteraction: options.requireInteraction,
            vibrate: options.vibrate || [200, 100, 200]
          }
        },
        delay
      }
    });
  }

  // 获取推送订阅状态
  public async getSubscriptionStatus(): Promise<{
    supported: boolean;
    subscribed: boolean;
    permission: NotificationPermission;
    subscription?: PushSubscription;
  }> {
    const supported = 'serviceWorker' in navigator && 'PushManager' in window;
    const permission = 'Notification' in window ? Notification.permission : 'denied';
    
    let subscribed = false;
    let subscription: PushSubscription | undefined;

    if (supported && this.serviceWorkerRegistration) {
      try {
        subscription = await this.serviceWorkerRegistration.pushManager.getSubscription() || undefined;
        subscribed = !!subscription;
      } catch (error) {
        console.error('获取订阅状态失败:', error);
      }
    }

    return {
      supported,
      subscribed,
      permission,
      subscription
    };
  }

  // 测试推送通知
  public async testPushNotification(): Promise<void> {
    await this.showNotification({
      title: '🔔 PWA推送测试',
      body: '这是一个PWA推送通知测试',
      tag: 'test-notification',
      actions: [
        { action: 'view', title: '查看' },
        { action: 'dismiss', title: '忽略' }
      ],
      data: {
        test: true,
        timestamp: Date.now()
      }
    });
  }

  // 私有方法

  private async fetchVapidPublicKey(): Promise<void> {
    try {
      // 从服务器获取VAPID公钥
      console.log('🌐 请求VAPID公钥: /api/push/vapid-public-key');
      const response = await fetch('/api/push/vapid-public-key');
      console.log('📡 VAPID API响应状态:', response.status, response.statusText);
      
      if (response.ok) {
        const data = await response.json();
        console.log('📄 VAPID API响应数据:', data);
        this.vapidPublicKey = data.publicKey;
        console.log('✅ 从服务器获取VAPID公钥成功');
      } else {
        // 如果服务器不可用，使用默认的测试公钥
        console.warn('⚠️ 无法从服务器获取VAPID公钥，使用默认公钥');
        this.vapidPublicKey = 'BCwA-MJHWcmZBteCFD2Am3oI5Hhcv9ORp8DKXLwYwSLB0yHCv4cOMwcse_DnFEKu9jXUwXMqKYtFtObQOyMmoVE';
      }
    } catch (error) {
      console.error('❌ 获取VAPID公钥失败:', error);
      // 使用默认公钥
      console.log('🔄 使用默认VAPID公钥');
      this.vapidPublicKey = 'BCwA-MJHWcmZBteCFD2Am3oI5Hhcv9ORp8DKXLwYwSLB0yHCv4cOMwcse_DnFEKu9jXUwXMqKYtFtObQOyMmoVE';
    }
  }

  private async syncSubscriptionToServer(subscription: PushSubscription): Promise<void> {
    try {
      const subscriptionData: PWASubscription = {
        endpoint: subscription.endpoint,
        keys: {
          p256dh: this.arrayBufferToBase64(subscription.getKey('p256dh')!),
          auth: this.arrayBufferToBase64(subscription.getKey('auth')!)
        }
      };

      console.log('📤 发送订阅数据到服务器:', subscriptionData);

      const response = await fetch('/api/push/subscribe', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(subscriptionData)
      });

      console.log('📡 订阅API响应状态:', response.status, response.statusText);

      if (response.ok) {
        const result = await response.json();
        console.log('✅ 订阅同步成功:', result);
      } else {
        console.warn('⚠️ 同步推送订阅到服务器失败:', response.status);
      }
    } catch (error) {
      console.error('❌ 同步推送订阅失败:', error);
    }
  }

  private async removeSubscriptionFromServer(subscription: PushSubscription): Promise<void> {
    try {
      const response = await fetch('/api/push/unsubscribe', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          endpoint: subscription.endpoint
        })
      });

      if (!response.ok) {
        console.warn('从服务器删除推送订阅失败');
      }
    } catch (error) {
      console.error('删除推送订阅失败:', error);
    }
  }

  private urlBase64ToUint8Array(base64String: string): Uint8Array {
    console.log('🔧 转换VAPID公钥:', base64String);
    try {
      const padding = '='.repeat((4 - base64String.length % 4) % 4);
      const base64 = (base64String + padding)
        .replace(/-/g, '+')
        .replace(/_/g, '/');
      
      console.log('🔧 处理后的base64:', base64);

      const rawData = window.atob(base64);
      const outputArray = new Uint8Array(rawData.length);

      for (let i = 0; i < rawData.length; ++i) {
        outputArray[i] = rawData.charCodeAt(i);
      }
      
      console.log('✅ VAPID公钥转换成功, 长度:', outputArray.length);
      return outputArray;
    } catch (error) {
      console.error('❌ VAPID公钥转换失败:', error);
      throw error;
    }
  }

  private arrayBufferToBase64(buffer: ArrayBuffer): string {
    const bytes = new Uint8Array(buffer);
    let binary = '';
    for (let i = 0; i < bytes.byteLength; i++) {
      binary += String.fromCharCode(bytes[i]);
    }
    return window.btoa(binary);
  }

  private handleNotificationClick(data: any): void {
    console.log('通知被点击:', data);
    
    // 触发自定义事件
    window.dispatchEvent(new CustomEvent('pwa-notification-click', {
      detail: data
    }));
  }

  private handleNotificationClose(data: any): void {
    console.log('通知被关闭:', data);
    
    // 触发自定义事件
    window.dispatchEvent(new CustomEvent('pwa-notification-close', {
      detail: data
    }));
  }

  private handleNavigation(url: string): void {
    console.log('导航到:', url);
    
    // 使用路由导航
    if (window.location.hash !== url) {
      window.location.hash = url;
    }
  }

  // 获取Service Worker注册信息
  public getServiceWorkerRegistration(): ServiceWorkerRegistration | null {
    return this.serviceWorkerRegistration;
  }

  // 获取推送订阅信息
  public getPushSubscription(): PushSubscription | null {
    return this.pushSubscription;
  }

  // 更新Service Worker
  public async updateServiceWorker(): Promise<void> {
    if (!this.serviceWorkerRegistration) return;

    try {
      await this.serviceWorkerRegistration.update();
      console.log('Service Worker 更新检查完成');
    } catch (error) {
      console.error('Service Worker 更新失败:', error);
    }
  }

  // 清除缓存
  public async clearCache(): Promise<void> {
    if (!this.serviceWorkerRegistration?.active) return;

    return new Promise((resolve, reject) => {
      const messageChannel = new MessageChannel();
      
      messageChannel.port1.onmessage = (event) => {
        if (event.data.type === 'CACHE_CLEARED') {
          if (event.data.success) {
            console.log('缓存已清除');
            resolve();
          } else {
            reject(new Error('清除缓存失败'));
          }
        }
      };

      this.serviceWorkerRegistration!.active!.postMessage({
        type: 'CLEAR_CACHE'
      }, [messageChannel.port2]);
    });
  }

  // 诊断推送订阅问题
  private async diagnosePushIssues(): Promise<void> {
    console.log('🔍 开始诊断推送订阅问题...');
    
    try {
      // 检查基本支持
      const checks = {
        serviceWorkerSupported: 'serviceWorker' in navigator,
        pushManagerSupported: 'PushManager' in window,
        notificationSupported: 'Notification' in window,
        serviceWorkerActive: !!this.serviceWorkerRegistration?.active,
        pushManagerAvailable: !!this.serviceWorkerRegistration?.pushManager,
        notificationPermission: Notification.permission,
        connectionStatus: navigator.onLine,
        protocol: location.protocol,
        hostname: location.hostname,
        userAgent: navigator.userAgent,
        language: navigator.language
      };
      
      console.log('📊 支持性检查:', checks);
      
      // 检查推送管理器权限状态
      if (this.serviceWorkerRegistration?.pushManager) {
        try {
          const permissionState = await this.serviceWorkerRegistration.pushManager.permissionState({
            userVisibleOnly: true
          });
          console.log('🔐 推送权限状态:', permissionState);
        } catch (error) {
          console.error('❌ 无法检查推送权限状态:', error);
        }
      }
      
      // 检查现有订阅
      if (this.serviceWorkerRegistration?.pushManager) {
        try {
          const existingSubscription = await this.serviceWorkerRegistration.pushManager.getSubscription();
          console.log('📋 现有订阅状态:', existingSubscription ? '存在' : '不存在');
          if (existingSubscription) {
            console.log('📋 现有订阅详情:', {
              endpoint: existingSubscription.endpoint,
              expirationTime: existingSubscription.expirationTime
            });
          }
        } catch (error) {
          console.error('❌ 无法检查现有订阅:', error);
        }
      }
      
      // 网络连接诊断
      await this.diagnoseNetworkConnectivity();
      
    } catch (error) {
      console.error('❌ 诊断过程出错:', error);
    }
  }

  // 诊断网络连接性
  private async diagnoseNetworkConnectivity(): Promise<void> {
    console.log('🌐 开始网络连接诊断...');
    
    // 测试关键服务的连接性
    const testEndpoints = [
      { name: 'FCM (Firebase Cloud Messaging)', url: 'https://fcm.googleapis.com/fcm/send' },
      { name: 'Google APIs', url: 'https://www.googleapis.com/generate_204' },
      { name: 'Mozilla Push Service', url: 'https://updates.push.services.mozilla.com/' },
      { name: 'Microsoft Push Service', url: 'https://wns2-sin1.notify.windows.com/' }
    ];
    
    const connectivityResults = [];
    
    for (const endpoint of testEndpoints) {
      try {
        console.log(`🔍 测试连接: ${endpoint.name}`);
        const startTime = Date.now();
        
        // 使用fetch测试连接，设置短超时
        const controller = new AbortController();
        const timeoutId = setTimeout(() => controller.abort(), 5000);
        
        const response = await fetch(endpoint.url, {
          method: 'HEAD',
          mode: 'no-cors', // 避免CORS问题
          signal: controller.signal
        });
        
        clearTimeout(timeoutId);
        const duration = Date.now() - startTime;
        
        connectivityResults.push({
          service: endpoint.name,
          status: 'success',
          duration: `${duration}ms`,
          type: response.type
        });
        
        console.log(`✅ ${endpoint.name}: 连接成功 (${duration}ms)`);
        
      } catch (error) {
        connectivityResults.push({
          service: endpoint.name,
          status: 'failed',
          error: error instanceof Error ? error.message : String(error),
          type: 'error'
        });
        
        console.log(`❌ ${endpoint.name}: 连接失败 -`, error);
      }
    }
    
    console.log('🌐 网络连接诊断结果:', connectivityResults);
    
    // 分析结果并给出建议
    const failedConnections = connectivityResults.filter(r => r.status === 'failed');
    if (failedConnections.length > 0) {
      console.log('⚠️ 检测到网络连接问题:');
      failedConnections.forEach(conn => {
        console.log(`   - ${conn.service}: ${conn.error}`);
      });
      
      console.log('💡 可能的解决方案:');
      console.log('   1. 检查防火墙设置，允许访问推送服务');
      console.log('   2. 如果在公司网络，联系网络管理员');
      console.log('   3. 尝试使用其他网络环境');
      console.log('   4. 使用VPN或代理服务');
      console.log('   5. 联系系统管理员配置网络白名单');
    }
  }

  // 发送测试推送通知
  public async sendTestNotification(): Promise<void> {
    if (!this.pushSubscription) {
      throw new Error('未订阅推送通知');
    }

    try {
      // 调用后端API发送测试推送
      const response = await fetch('/api/push/test', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          subscription: this.pushSubscription.toJSON(),
          payload: {
            title: '🔔 PWA测试推送',
            body: '这是一条PWA推送通知测试消息',
            icon: '/icon-192x192.png',
            tag: 'pwa-test'
          }
        })
      });

      if (!response.ok) {
        throw new Error(`测试推送失败: ${response.status}`);
      }

      console.log('✅ PWA测试推送发送成功');
    } catch (error) {
      console.error('❌ PWA测试推送失败:', error);
      throw error;
    }
  }
}

export default PWANotificationService;
